package gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Observable;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

import model.User;
import model.UserType;


/**
 * The Calendar GUI.
 * Tutorial was used to assist in creating
 * the calendar. URL:
 * http://www.dreamincode.net/forums/topic/25042-creating-a-calendar-viewer-application/page__st__15
 * 
 * @author Prince Kishore
 *
 */
public class CopyOfCalendarGUI extends Observable
{
    public static final String[] MONTHS = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
    
	private final int WIDTH = 800;
	private final int HEIGHT = 600;
	private final int ROW_HEIGHT = 73;
	private JLabel my_month_label;
	private JLabel my_year_label;
	private JButton my_prev_button;
	private JButton my_next_button;
	private JButton my_add_auction_button;
	private JTable my_calendar_table;
	private JComboBox my_year_drop_down;
	private JFrame my_main_frame;
	private Container my_pane;
	private DefaultTableModel my_calendar_table_model;
	private JScrollPane my_calendar_scroller;
	private JPanel my_calendar_panel;
	private int my_actual_day, my_actual_month, 
				my_actual_year, my_current_month, 
				my_current_year;
	private User my_cur_user;
	
	
	
	/**
	 * The constructor.
	 * @param the_cur_user Current user.
	 */
	public CopyOfCalendarGUI (User the_cur_user)
	{
		my_cur_user = the_cur_user;

        prepareFrame();
        createControllers();
        addControls();
        setBounds();
        
        obtainDate();
        formatCalendar();   
        refreshCalendar(my_actual_month, my_actual_year);
        addActions();
	}
	
	
	
	public static void main(String args[])
	{
		User temp_user = new User("Joe", UserType.NPO, "NPO");
		CopyOfCalendarGUI calendar = new CopyOfCalendarGUI(temp_user);
		calendar.start();
	}
	
	
	
	/**
	 * Starts the calendar GUI.
	 */
	@SuppressWarnings("serial")
	public void start ()
	{
		try
		{
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch (ClassNotFoundException e) {}
		catch (InstantiationException e) {}
		catch (IllegalAccessException e) {}
		catch (UnsupportedLookAndFeelException e) {}
		
		prepareFrame();
		createControllers();
		addControls();
		setBounds();
		
		my_main_frame.setResizable(false);
		my_main_frame.setVisible(true);
		
		obtainDate();
		formatCalendar();	
		refreshCalendar(my_actual_month, my_actual_year);
		addActions();
	}
	
	
	
	/**
	 * Formats the calendar and sets headers for the days.
	 */
	private void formatCalendar()
	{
		//Add the day headers
				String[] headers = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
				
				for (int i = 0; i < 7; i++)
				{
					my_calendar_table_model.addColumn(headers[i]);
				}
				
				//Set Background Color (White)
				my_calendar_table.getParent().setBackground(my_calendar_table.getBackground());
				
				//Disable Resize
				my_calendar_table.getTableHeader().setResizingAllowed(false);
				
				//Disable Reorder
				my_calendar_table.getTableHeader().setReorderingAllowed(false);
				
				//Single cell Selection only
				my_calendar_table.setColumnSelectionAllowed(true);
				my_calendar_table.setRowSelectionAllowed(true);
				my_calendar_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
				
				//Set row/column height
				my_calendar_table.setRowHeight(ROW_HEIGHT);
				my_calendar_table_model.setColumnCount(7);
				my_calendar_table_model.setRowCount(6);
				
				//Prepare Calendar
				for (int i = my_actual_year - 10; i <= my_actual_year + 10; i++)
				{
					my_year_drop_down.addItem(String.valueOf(i));
				}
				
				//Setting the border
				my_calendar_panel.setBorder(BorderFactory.createTitledBorder("Calendar"));
				
				//Font of month label
				my_month_label.setFont(new Font("Arial", Font.BOLD, 16));

	}
	
	
	
	/**
	 * Adds the action listeners to the buttons.
	 */
	private void addActions()
	{
		my_prev_button.addActionListener(new previousButtonAction());
		my_next_button.addActionListener(new nextButtonAction());
		my_year_drop_down.addActionListener(new yearDropDownAction());
		my_add_auction_button.addActionListener(new addAuctionAction());
	}
	
	
	
	/**
	 * Gets the actual date of today.
	 */
	private void obtainDate()
	{
		GregorianCalendar calendar = new GregorianCalendar();
		my_actual_day = calendar.get(GregorianCalendar.DAY_OF_MONTH);
		my_actual_month = calendar.get(GregorianCalendar.MONTH);
		my_actual_year = calendar.get(GregorianCalendar.YEAR);
		my_current_month = my_actual_month;
		my_current_year = my_actual_year;		
	}
	
	
	
	/**
	 * Creates the labels, buttons, and JTable for the calendar.
	 */
	private void createControllers()
	{
		my_month_label = new JLabel ("January");
		my_year_label = new JLabel ("Change Year:");
		my_year_drop_down = new JComboBox();
		my_prev_button = new JButton("<<");
		my_next_button = new JButton(">>");
		my_add_auction_button = new JButton("Add Auction");
		my_calendar_table_model = new DefaultTableModel() 
		{
			public boolean isCellEditable(int rowIndex, int colIndex) 
			{
				return false; //true allows for editing of day tags in the calender day boxes,
				              //may be useful for something like editing auctions, but not likely.
			}
		};
		my_calendar_table = new JTable(my_calendar_table_model);
		my_calendar_scroller = new JScrollPane(my_calendar_table);
		my_calendar_panel = new JPanel(null); //creates panel to place components
	}
	
	
	
	/**
	 * Creates the frame and adds the calendar panel
	 * to the frame.
	 */
	private void prepareFrame()
	{
		my_main_frame = new JFrame("AuctionCentral Calendar");
		my_main_frame.setSize(new Dimension(WIDTH, HEIGHT));
		my_pane = my_main_frame.getContentPane();
		my_pane.setLayout(null);
		my_main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	
	
	/**
	 * Adds buttons and other controls to the calendar.
	 */
	private void addControls()
	{
		my_pane.add(my_calendar_panel);
		my_calendar_panel.add(my_month_label);
		my_calendar_panel.add(my_year_label);
		my_calendar_panel.add(my_year_drop_down);
		my_calendar_panel.add(my_prev_button);
		my_calendar_panel.add(my_next_button);
		my_calendar_panel.add(my_calendar_scroller);
		if (my_cur_user.my_user_type != UserType.BIDDER)
		{
			my_calendar_panel.add(my_add_auction_button);
		}
	}
	
	
	
	/**
	 * Sets the location of each item on the calendar.
	 */
	private void setBounds()
	{
		my_calendar_panel.setBounds(5, 10, 475, 560);
		my_month_label.setBounds(250 - my_month_label.getPreferredSize().width/2, 25, 180, 25);
		my_year_label.setBounds(310, 525, 80, 20);
		my_year_drop_down.setBounds(385, 525, 80, 20);
		my_prev_button.setBounds(10, 20, 50, 25);
		my_next_button.setBounds(65, 20, 50, 25);
		my_calendar_scroller.setBounds(10, 50, 455, 465);
		my_add_auction_button.setBounds(375, 20, 90, 25);
	}
	
	
	
	/**
	 * Refreshes the calendar for any changes to the month or year. 
	 * @param the_month The month.
	 * @param the_year The year.
	 */
	private void refreshCalendar(int the_month, int the_year)
	{
		
		int number_of_days;
		int start_of_month;
		
		my_prev_button.setEnabled(true);
		my_next_button.setEnabled(true);
		
		//Limits the years so that you cannot access a date too early or too late
		if (the_month == 0 && the_year <= 2012) //removed - 10, no reason to go 10 years back 
		                                                  //from whenever they'd start computerized auctions.
		{
			my_prev_button.setEnabled(false);
		}
		
		if (the_month == 11 && the_year >= my_actual_year + 10)
		{
			my_next_button.setEnabled(false);
		}
		
		my_month_label.setText(MONTHS[the_month]); //updates the month label
		
		my_month_label.setBounds(250 - my_month_label.getPreferredSize().width/2, 25, 180, 25); // Re-aligns the label
		
		my_year_drop_down.setSelectedItem(String.valueOf(the_year));
		
		//Get 1st day of the month and the number of days in that month
		GregorianCalendar calendar = new GregorianCalendar(the_year, the_month, 1);
		number_of_days = calendar.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
		start_of_month = calendar.get(GregorianCalendar.DAY_OF_WEEK);
		
		//Clear Table
		for (int i = 0; i < 6; i++)
		{
			for (int j = 0; j < 7; j++)
			{
				my_calendar_table_model.setValueAt(null, i, j);
			}
		}
		
		//Draw calendar dates
		for (int i = 1; i <= number_of_days; i++)
		{
			int row = new Integer((i + start_of_month - 2) / 7);
			int column = (i + start_of_month - 2) % 7;
			my_calendar_table_model.setValueAt(i, row, column);
		}
		
		my_calendar_table.setDefaultRenderer(my_calendar_table.getColumnClass(0), new calendarTableRenderer());
	}
	
	
	
	/**
	 * Renders background, selection, and other visual formatting.
	 * @author Prince Kishore
	 * @version 5/23/12
	 */
	@SuppressWarnings("serial")
	private class calendarTableRenderer extends DefaultTableCellRenderer
	{
		public Component getTableCellRendererComponent (JTable table, Object value, boolean selected, boolean focused, int row, int column)
		{
			super.getTableCellRendererComponent(table, value, selected, focused, row, column);
			if (value != null)
			{
				setBackground(Color.WHITE);
				if (Integer.parseInt(value.toString()) == my_actual_day && my_current_month == my_actual_month && my_current_year == my_actual_year && !selected)
				{
					setBackground(new Color(220, 220, 255));
				}
				
				else if (selected)
				{
					//If a cell is selected
					System.out.println(table.getValueAt(row, column)); //Okay this can be used to get a date!
					setBackground(new Color(255, 215, 0)); //highlight selected cell
				}
				else 
				{
					setBackground(Color.WHITE);
					
				}
			}
			setBorder(null);
			setForeground(Color.BLACK);
			return this;
		}
		
	}
	
	
	
	/**
	 * Gets the default table renderer for customization.
	 * @author Prince Kishore
	 *
	 */
	private class calendarRenderer extends DefaultTableCellRenderer
	{
		public Component getTableCellRendererComponent (JTable table, Object value, boolean selected, boolean focused, int row, int column)
		{
			super.getTableCellRendererComponent(table, value, selected, focused, row, column);
			return this;
		}
	}
	
	
	
	/**
	 * The previous button action. Moves calendar back one month.
	 * @author Prince Kishore
	 * @version 5/4/12
	 *
	 */
	private class previousButtonAction implements ActionListener
	{
		public void actionPerformed(ActionEvent the_event)
		{
			if (my_current_month == 0)
			{
				my_current_month = 11;
				my_current_year -= 1;
			}
			else
			{
				my_current_month -= 1;
			}
			refreshCalendar(my_current_month, my_current_year);
		}
	}
	
	
	
	/**
	 * The next button action. Forwards the calendar by one month.
	 * @author Prince Kishore
	 * @version 5/4/12
	 *
	 */
	private class nextButtonAction implements ActionListener
	{
		public void actionPerformed(ActionEvent the_event)
		{
			//If December, add a year too else, only add a month.
			if (my_current_month == 11)
			{
				my_current_month = 0;
				my_current_year += 1;
			}
			else
			{
				my_current_month += 1;
			}
			refreshCalendar(my_current_month, my_current_year);
		}
	}
	
	
	
	/**
	 * The year drop down menu action. Changes the year.
	 * @author Prince Kishore
	 * @version 5/4/12
	 *
	 */
	private class yearDropDownAction implements ActionListener
	{
		public void actionPerformed (ActionEvent the_event)
		{
			if (my_year_drop_down.getSelectedItem() != null)
			{
				String temp = my_year_drop_down.getSelectedItem().toString();
				my_current_year = Integer.parseInt(temp);
				
				refreshCalendar(my_current_month, my_current_year);
			}
		}
	}
	
	
	/**
	 * the getPanel method to return the calendarPanel to display.
	 * 
	 * @author Travis Drake
	 * @return my_calendar_panel.
	 */
	public JPanel getPanel()
	{
	    return my_calendar_panel;
	}
	
	
	/**
	 * The add auction action.
	 * @author Prince Kishore
	 * @version 5/14/12
	 *
	 */
	private class addAuctionAction implements ActionListener
	{
		public void actionPerformed (ActionEvent the_event)
		{
		    setChanged();
		    notifyObservers("ADD_AUCTION");
		}
	}
}
